# -*- coding: utf-8 -*-
import cv2 as cv

img = cv.imread("photos/dog.jpg")
cv.imshow("Dog", img)

gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow("Gray", gray)

# CascadeClassifier为OpenCV下用来做目标检测的级联分类器的一个类。
# 该类中封装的目标检测机制，简而言之是滑动窗口机制+级联分类器的方式

# xml中存放的是训练后的特征池，特征size大小根据训练时的参数而定，
# 检测的时候可以简单理解为就是将每个固定size特征（检测窗口）与输入图像的同样大小区域比较，
# 如果匹配那么就记录这个矩形区域的位置，然后滑动窗口，检测图像的另一个区域，重复操作。
# 由于输入的图像中特征大小不定，比如在输入图像中眼睛是50x50的区域，而训练时的是25x25，
# 那么只有当输入图像缩小到一半的时候，才能匹配上，所以这里还有一个逐步缩小图像，
# 也就是制作图像金字塔的流程
# 由于人脸可能出现在图像的任何位置，在检测时用固定大小的窗口对图像从上到下、从左到右扫描，
# 判断窗口里的子图像是否为人脸，这称为滑动窗口技术（sliding window）。
# 为了检测不同大小的人脸，还需要对图像进行放大或者缩小构造图像金字塔，对每张缩放后的图像都用上面的方法进行扫描。
# 由于采用了滑动窗口扫描技术，并且要对图像进行反复缩放然后扫描，因此整个检测过程会非常耗时。

# Haar级联分类器： 通过分析对比相邻图像区域来判断给定图像或者图像区域与已知对象是否匹配。
# Haar特征具有尺度不变性，但其并不具有旋转不变性。
# 举个例子，opencv提供的Haar级联分类器并不认为侧脸和正脸一样，倒置的人脸和正脸一样。
haar_cascade = cv.CascadeClassifier("haarcascade_frontalface_default.xml")

print(cv.__file__)

# scaleFactor –缩放因子（default：1.1）
# minNeighbors – 被检查为目标的相邻区域的最小个数（default： 3） 
# 个人理解是如果某个区域被连续至少三次检测到，则该区域可判定为目标物体
face_rect = haar_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighors=3)

print(f'Number of faces found = {len(face_rect)}')

for (x,y,w,h) in face_rect:
    cv.rectangle(img, (x,y), (x+w, y+h), (0,255,0), thickness=2)
cv.imshow("Dectected Faces", img)    


cv.waitKey(0)